//
// Created by jack on 2021/2/6.
//

#include "weilapb_defines.h"

#include <WL.Service.pb.h>
#include <WL.User.pb.h>
#include <pb_decode.h>

#include "weilapb_datafuns.h"

#include "weilapb_commondec.h"
#include "weilapb_error.h"
#include "weilapb_internal.h"
#include "weilapb_user.h"

PBWeilaMsg* weilapb_decodeChangeUserInfoNtf(const PB_UINT8* pData, PB_UINT32 dataSize) {
    WL_Service_ServiceMessage serviceMessage = WL_Service_ServiceMessage_init_zero;
    pb_istream_t              istream;
    PBWeilaMsg*               pWeilaMsg = PB_ALLOC(sizeof(PBWeilaMsg) + sizeof(PBUserInfo));

    istream = pb_istream_from_buffer(pData, dataSize);

    if (pWeilaMsg) {
        PBUserInfo*         pUserInfo;
        WL_Common_UserInfo* pAttr;
        PBFieldData         fieldData[USER_COUNT];
        pWeilaMsg->contentSize = sizeof(PBUserInfo);

        pUserInfo = (PBUserInfo*)pWeilaMsg->pContent;
        pAttr     = &(serviceMessage.userMessage.ntfChangeUserInfo.userInfo);
        weilapb_prepareUserInfoField(fieldData, pAttr, pUserInfo);

        if (weilapb_decodeWeilaMsg(pWeilaMsg, &istream, &serviceMessage)) {
            if (serviceMessage.has_userMessage && serviceMessage.userMessage.has_ntfChangeUserInfo) {
                if (serviceMessage.userMessage.ntfChangeUserInfo.has_userInfo) {
                    if (serviceMessage.userMessage.ntfChangeUserInfo.userInfo.has_userId) {
                        pUserInfo->userId = serviceMessage.userMessage.ntfChangeUserInfo.userInfo.userId;
                    }
                    if (serviceMessage.userMessage.ntfChangeUserInfo.userInfo.has_sex) {
                        pUserInfo->sex = serviceMessage.userMessage.ntfChangeUserInfo.userInfo.sex;
                    }
                }
            }
            return pWeilaMsg;
        }
        weilapb_error(ERR_DECODE, "decode msg data fail");
        PB_FREE(pWeilaMsg);
        pWeilaMsg = PB_NULL;
    } else {
        weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
    }

    return pWeilaMsg;
}

PBWeilaMsg* weilapb_decodeSetConfigNtf(const PB_UINT8* pData, PB_UINT32 dataSize) {
    WL_Service_ServiceMessage serviceMessage = WL_Service_ServiceMessage_init_zero;
    pb_istream_t              istream;
    PBWeilaMsg*               pWeilaMsg = PB_ALLOC(sizeof(PBWeilaMsg) + MAX_LONG_STRING_LEN);

    istream = pb_istream_from_buffer(pData, dataSize);
    if (pWeilaMsg) {
        PBFieldData contentField;
        PB_CHAR*    pConfig    = (PB_CHAR*)pWeilaMsg->pContent;
        pWeilaMsg->contentSize = MAX_LONG_STRING_LEN;

        weilapb_initDecDataItem(&contentField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_LONG_STRING_LEN, pConfig);
        weilapb_setDecCallback(&contentField, &serviceMessage.userMessage.ntfSetConfig.config, PB_NULL);

        if (weilapb_decodeWeilaMsg(pWeilaMsg, &istream, &serviceMessage)) {
            return pWeilaMsg;
        }

        weilapb_error(ERR_DECODE, "decode msg data fail");
        PB_FREE(pWeilaMsg);
        pWeilaMsg = PB_NULL;
    } else {
        weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
    }

    return pWeilaMsg;
}

PBWeilaMsg* weilapb_decodeGetConfigRsp(const PB_UINT8* pData, PB_UINT32 dataSize) {
    WL_Service_ServiceMessage serviceMessage = WL_Service_ServiceMessage_init_zero;
    pb_istream_t              istream;
    PBWeilaMsg*               pWeilaMsg = PB_ALLOC(sizeof(PBWeilaMsg) + MAX_LONG_STRING_LEN);

    istream = pb_istream_from_buffer(pData, dataSize);

    if (pWeilaMsg) {
        PBFieldData configInfoField;
        PB_CHAR*    pConfig    = (PB_CHAR*)pWeilaMsg->pContent;
        pWeilaMsg->contentSize = MAX_LONG_STRING_LEN;

        weilapb_initDecDataItem(&configInfoField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_LONG_STRING_LEN, pConfig);
        weilapb_setDecCallback(&configInfoField, &serviceMessage.userMessage.rspGetConfig.config, PB_NULL);

        if (weilapb_decodeWeilaMsg(pWeilaMsg, &istream, &serviceMessage)) {
            return pWeilaMsg;
        }

        weilapb_error(ERR_DECODE, "decode msg data fail");
        PB_FREE(pWeilaMsg);
        pWeilaMsg = PB_NULL;
    } else {
        weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
    }

    return pWeilaMsg;
}

PBWeilaMsg* weilapb_decodeUserMsg(PB_INT32 commandId, PB_INT32 commandType, const PB_UINT8* pData, PB_UINT32 dataSize) {
    PBWeilaMsg* pPbWeilaMsg = PB_NULL;

    switch (commandId) {
        case WL_User_UserCommandId_USER_COMMAND_CHANGE_USERINFO: {
            if (commandType == WL_Service_CommandType_COMMAND_NOTIFY) {
                pPbWeilaMsg = weilapb_decodeChangeUserInfoNtf(pData, dataSize);
            }
            if (pPbWeilaMsg) {
                pPbWeilaMsg->message = WL_USER_CHANGE_USER_INFO_MSG;
            }
        } break;

        case WL_User_UserCommandId_USER_COMMAND_GET_CONFIG: {
            pPbWeilaMsg = weilapb_decodeGetConfigRsp(pData, dataSize);
            if (pPbWeilaMsg) {
                pPbWeilaMsg->message = WL_USER_GET_CONFIG_MSG;
            }
        } break;

        case WL_User_UserCommandId_USER_COMMAND_SET_CONFIG: {
            if (commandType == WL_Service_CommandType_COMMAND_RESPONSE) {
                pPbWeilaMsg = weilapb_decodeEmptyRsp(pData, dataSize);
            } else {
                pPbWeilaMsg = weilapb_decodeSetConfigNtf(pData, dataSize);
            }

            if (pPbWeilaMsg) {
                pPbWeilaMsg->message = WL_USER_SET_CONFIG_MSG;
            }
        } break;
    }

    return pPbWeilaMsg;
}

// request

PBEncResult weilapb_buildUserReq(PB_UINT16 commandId, WL_User_UserMessage* pParam) {
    PBEncResult                pbResult;
    WL_Service_ServiceMessage* pServiceMessage =
        weilapb_buildServiceMsg(WL_Service_ServiceID_SERVICE_USER, commandId, WL_Service_CommandType_COMMAND_REQUEST);

    memset(&pbResult, 0, sizeof(PBEncResult));
    pbResult.message = weilapb_getMessageByCommandId(WL_Service_ServiceID_SERVICE_USER, commandId);
    if (pServiceMessage) {
        pServiceMessage->has_userMessage = true;
        memcpy(&pServiceMessage->userMessage, pParam, sizeof(WL_User_UserMessage));
        if (weilapb_encodeWeilaMsg(pServiceMessage, &pbResult)) {
            PB_FREE(pServiceMessage);
            return pbResult;
        } else {
            PB_FREE(pServiceMessage);
            pbResult.errCode = ERR_ENCODE;
        }
    } else {
        pbResult.errCode = ERR_OUT_OF_MEMORY;
    }

    return pbResult;
}

PBEncResult weilapb_buildChangeUserInfoReq(PBChangeUserInfo* pChangeUserInfo) {
    PBFieldData         nickField;
    PBFieldData         avatarField;
    PBFieldData         signatureField;
    WL_User_UserMessage wlUserUserMessage = WL_User_UserMessage_init_zero;

    wlUserUserMessage.has_reqChangeUserInfo     = true;
    wlUserUserMessage.reqChangeUserInfo.has_sex = pChangeUserInfo->changeSex;
    wlUserUserMessage.reqChangeUserInfo.sex     = pChangeUserInfo->sex;

    if (pChangeUserInfo->changeNick) {
        weilapb_initEncDataItem(
            &nickField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_SHORT_STRING_LEN, pChangeUserInfo->nick);
        weilapb_setEncCallback(&nickField, &wlUserUserMessage.reqChangeUserInfo.nick, PB_NULL);
    }

    if (pChangeUserInfo->changeAvatar) {
        weilapb_initEncDataItem(
            &avatarField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_URL_STRING_LEN, pChangeUserInfo->avatar);
        weilapb_setEncCallback(&avatarField, &wlUserUserMessage.reqChangeUserInfo.avatar, PB_NULL);
    }

    if (pChangeUserInfo->changeSignature) {
        weilapb_initEncDataItem(
            &signatureField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_NORMAL_STRING_LEN, pChangeUserInfo->signature);
        weilapb_setEncCallback(&signatureField, &wlUserUserMessage.reqChangeUserInfo.signature, PB_NULL);
    }

    return weilapb_buildUserReq(WL_User_UserCommandId_USER_COMMAND_CHANGE_USERINFO, &wlUserUserMessage);
}

PBEncResult weilapb_buildGetConfigReq() {
    WL_User_UserMessage wlUserUserMessage = WL_User_UserMessage_init_zero;
    return weilapb_buildUserReq(WL_User_UserCommandId_USER_COMMAND_GET_CONFIG, &wlUserUserMessage);
}

PBEncResult weilapb_buildSetConfigReq(PB_UINT32 userId, PB_CHAR* pKeyName, PB_CHAR* pContent) {
    PBFieldData         nameField;
    PBFieldData         contentField;
    WL_User_UserMessage wlUserUserMessage = WL_User_UserMessage_init_zero;

    wlUserUserMessage.reqSetConfig.has_userId = true;
    wlUserUserMessage.reqSetConfig.userId     = userId;

    weilapb_initEncDataItem(&nameField, PB_DATA_TYPE_FIXED_SIZE_STRING, strlen(pKeyName), pKeyName);
    weilapb_setEncCallback(&nameField, &wlUserUserMessage.reqSetConfig.name, PB_NULL);

    weilapb_initEncDataItem(&contentField, PB_DATA_TYPE_FIXED_SIZE_STRING, strlen(pContent), pContent);
    weilapb_setEncCallback(&contentField, &wlUserUserMessage.reqSetConfig.content, PB_NULL);

    return weilapb_buildUserReq(WL_User_UserCommandId_USER_COMMAND_SET_CONFIG, &wlUserUserMessage);
}
